/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package analiseSintatica.Regras.Expressoes;

import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.Regras.Regra;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;

/**
 *
 * @author linton
 */
public class RegraRelacional extends Regra {

    protected static Regra instancia;

    protected String estrutura = "<exp_aritmetica> {<op_relacional><exp_aritmetica>}";
    RegraExpAritmetica regraExpAritmetica = RegraExpAritmetica.getInstance();
    RegraOpRelacional regraOpRelacional = RegraOpRelacional.getInstance();


    /**
     * Construtor privado necessario ao singleton
     */
    private RegraRelacional() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraRelacional getInstance() {
        if (instancia == null) {
            instancia = new RegraRelacional();
        }
        return (RegraRelacional) instancia;
    }

    @Override
    public NoArvore analisar(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        NoArvore noRelacional = new NoArvore("<relacional>", false);
        noRelacional.adicionaFilho(reconhecerExp_Aritmetica(listaTokens));

        while(regraOpRelacional.getPrimeiro().contains(listaTokens.getFirst().getToken())){
            noRelacional.adicionaFilho(reconhecerOp_relacional(listaTokens));
            noRelacional.adicionaFilho(reconhecerExp_Aritmetica(listaTokens));
        }

        return noRelacional;
    }

    public NoArvore reconhecerExp_Aritmetica(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        LinkToken token = listaTokens.getFirst();
        if (regraExpAritmetica.getPrimeiro().contains(token.getToken())) {
            return regraExpAritmetica.analisar(listaTokens);
        }
        ErroSintaticoException erro = new ErroSintaticoException();
        erro.addErros("Falta expressao aritmetica", estrutura, token.getLinha());
        throw erro;

    }
    public NoArvore reconhecerOp_relacional(LinkedList<LinkToken> listaTokens) throws ErroSintaticoException {
        LinkToken token = listaTokens.getFirst();
        if (regraOpRelacional.getPrimeiro().contains(token.getToken())) {
            return regraOpRelacional.analisar(listaTokens);
        }
        ErroSintaticoException erro = new ErroSintaticoException();
        erro.addErros("Falta operador relacional", estrutura, token.getLinha());
        throw erro;

    }

    

    @Override
    protected void setPrimeiro() {
        //this.primeiro = getUniao(primeiro, RegraExpAritmetica.getInstance().getPrimeiro());
    //P<relacional> = P<cast>
        primeiro.add("(");
        primeiro.add("{");
        primeiro.add("identificador");
        primeiro.add("numeroInteiro");
        primeiro.add("numeroFlutuante");
        primeiro.add("charconst");
        primeiro.add("++");
        primeiro.add("--");
        primeiro.add("&");
        primeiro.add("*");
    }

    @Override
    protected void setSeguinte() {
     /*   this.seguinte = getUniao(this.seguinte, RegraIgualdade.getInstance().getSeguinte());
        this.seguinte = getUniao(this.seguinte, RegraOpIgualdade.getInstance().getPrimeiro());*/
        /*S<relacional>  =  P<op_igualdade> U S<igualdade>
             ->S<relacional>  = {"==" , "!=" } U {&&} U {'{'} U {identificador,
         "(", numeroInteiro , numeroFlutuante , charconst, '++', '--', '&', '*'}
                        U {";", ",", "}" ")"}*/
        this.seguinte.addAll(primeiro);
        this.seguinte.add("&&");
        this.seguinte.add(";");
        this.seguinte.add(",");
        this.seguinte.add("}");
        this.seguinte.add(")");
        this.seguinte.add("==");
        this.seguinte.add("!=");

    }
}
